<?
class Table {
	protected $log = null;
	protected $columns  = null;
	protected $pk = null;
	protected $db = null;
	protected $table = null;
	protected $sqlParser = null;
	
	public function Table($tableName,$connection){
		$this->log = Logger::getRootLogger();
		$this->table = $tableName;
		$this->db = $connection;
		$this->columns = $this->db->MetaColumns($this->table,true);
		$this->sqlParser= new SafeSQL_PG();
		$this->detectPrimaryKeys();
	}
		
	public function getPrimaryKeys(){
		if(!($this->pk)) $this->detectPrimaryKeys();
		return($this->pk);
	}
	
	public function isPrimaryKeyAutoNum(){
		foreach($this->getPrimaryKeys() as $c){
			if($c->primary_key){
				if(preg_match('/.*_seq.*$/',$c->default_value)){
					return(true);
				}
			}
		}
		return(false);
	}
	
	public function getPrimaryKeyAutoNum(){
		if(!($this->isPrimaryKeyAutoNum())) 
			return(null);
		
		foreach($this->getPrimaryKeys() as $c){
			if($c->primary_key){
				$this->log->debug($c->default_value);
				if(preg_match('/.*_seq.*$/',$c->default_value)){
					return($c->name);
				}
			}
		}
	}
		
	public function updateRow($params){
		try {
			if($this->findByPK($params)){
				$this->log->debug('updateRow: Update');
				$condition = $this->getPkCondition($params);
				return($this->executeUpdate($params,$condition));
			} else {
				$this->log->debug('updateRow: Insert');
				return($this->executeInsert($params));
			}			
		} catch (exception $e) {
			$this->log->error($e->getMessage());
			return(false);
		}		
	}
			
	public function deleteRow($params){
		$condition = $this->getPkCondition($params);
		$query = "delete from " . $this->table . " where ${condition}";				
		$this->log->debug("DELETE ROW FINAL QUERY:" . $query);
		return($this->db->Execute($query));
	}
	
	public function deleteRows($params) {
		$condition = $this->getConditionFromParams($params);
		$query = "delete from " . $this->table . " where ${condition}";				
		$this->log->debug("DELETE ROWS FINAL QUERY:" . $query);
		return($this->db->Execute($query));
	}
	
	public function findByPK($params){
		$condition = $this->getPkCondition($params);
		$query = "select * from " . $this->table . " where ${condition}";				
		$this->log->debug("FIND BY PK FINAL QUERY:" . $query);
		$this->log->debug("AUTONUM:" . $this->getPrimaryKeyAutoNum());
		return($this->db->getRow($query));
	}
	
	public function findRow($params){
		$condition = $this->getConditionFromParams($params);
		$query = "select * from " .  $this->table . " where ${condition}";
		$this->log->debug("FIND ROW FINAL QUERY:" . $query);
		return($this->db->getRow($query));	
	}
	
	public function findRows($params,$start=null,$limit=null,$sort = null, $dir = null){
		$condition = $this->getConditionFromParams($params);
		$query = "select * from " .  $this->table . " where ${condition}";				
		$this->log->debug("FIND ROWS FINAL QUERY:" . $query);
		return($this->GetAll($query,$start,$limit));	
	}
	
	public function getRows($start=null,$limit=null,$sort = null, $dir = null){
		return($this->findRows( array(), $start, $limit, $sort, $dir ));
	}
		
	protected function getPkCondition($params){
		$condition = " 1 = 1 ";
		$values = array();
	
		foreach($this->getPrimaryKeys() as $c){
			$condition .= " and " . $c->name . "=" . $this->getQuote($c->type);
			$values[] = $params[$c->name];
		}
		
		$this->log->debug("RAW CONDITION:" . $condition);
		$condition = $this->sqlParser->query($condition,$values);
		$this->log->debug("VALUES CONDITION:" . $condition);
		return($condition);
	}
	
	protected function getConditionFromParams($params){
		$condition = " 1 = 1 ";
		$values = array();
		foreach($params as $key=>$value){
			if ( ($c = $this->getColumn($key)) != null ){
				$condition .= " and " . $c->name . "=" . $this->getQuote($c->type);
				$values[] = $params[$c->name];
			}	
		}
		
		$this->log->debug("RAW CONDITION:" . $condition);
			$condition = $this->sqlParser->query($condition,$values);
		$this->log->debug("VALUES CONDITION:" . $condition);
		
		return($condition);
	}
		
	protected function GetAll($sql,$limit = null,$start = null){
		$sql_count = "select count(*) as cantidad from (${sql}) as temporal";
		$results = $this->db->GetOne($sql_count);
			
		if($limit!=null &&  $start !=null )
			$sql = "${sql} limit ${limit} offset ${start}";
		else {
			if($limit!=null)
				$sql = "${sql} limit ${limit} ";
		}
				
		$rows = $this->db->GetAll($sql);
		$result = array('rows'=>$rows, 'results' => $results);
		return($result);
	}
	
	protected function executeInsert($params){
		$colum_sequence_name = $this->getPrimaryKeyAutoNum();
		$this->log->debug("EXECUITING INSERT AUTONUM:" . $colum_sequence_name);
		unset($params[$colum_sequence_name]);
		
		$result  = $this->db->AutoExecute($this->table, $params,'INSERT');
		
		if($this->isPrimaryKeyAutoNum()){
			$autonum_name =  $this->table . "_" . $colum_sequence_name . "_seq";
			$result = $this->db->GetOne("select currval('${autonum_name}');");
			if($result){
				$params[$colum_sequence_name]  = $result;
				return($params);
			}					
		} else {
			return($params);	
		}
	}
	
	protected function executeUpdate($params,$where) {
		$result = $this->db->AutoExecute($this->table, $params, 'UPDATE', $where);
		return($params);
	}
	
	protected function detectPrimaryKeys(){
		$this->pk = array();
		foreach($this->columns as $c)
			if($c->primary_key) 
				$this->pk[] = $c;
	}
	
	protected function getColumn($columName){
		foreach($this->columns as $c)
			if($c->name == $columName) 
				return($c);
		return(null);
	}
	
	//completar
	protected function getQuote($type){
		$this->log->debug("Type Column:" . $type);
		switch($type){
			case 'int4' : return('%i');
			default : return("'%s'");
		}
	}
	
}

?>